package com.thinking.in.spring.ioc.dependency.injection;

import com.think.in.spring.ioc.overview.domain.User;
import com.thinking.in.spring.ioc.dependency.injection.annotation.InjectedUser;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import javax.inject.Inject;
import java.lang.annotation.Annotation;
import java.util.*;

/**
 * 注解驱动  ：依赖注入处理过程
 *
 * @author zjiajia
 * @date 2021/12/31 13:17
 */
public class AnnotationDependencyInjectionResolutionDemo {

    /**
     * 场景 一 ： 注入单个 Bean
     *
     * @Autowired 依赖查找（处理）
     *
     * DependencyDescriptor相关信息 :
     *      是否必须 ： required = true
     *      是否实时 ： eager = true
     *      通过类型 ： User.class
     *      字段名称 ： "user"
     *      是否首要 ： primary  = true
     *
     *
     *
     */
  //  @Autowired
  //  private User user;



    /**
     * 场景二 ：注入多个 Bean
     *
     * user  superUser
     *
     *
     */
   // @Autowired
   // private Map<String,User> userMap;

    /**
     *
     * 场景三 ： optional
     *
     *
     *
     */
    @Autowired
    private Optional<User> optionalUser;


    @Inject
    private User injectUser;

    @InjectedUser
    private User injectedUser;

    /**
     * 注意点：
     *      方法要是static 的才可以 , 这样 bean的创建就脱离了 对象的创建,可以优先与对象创建出来
     *
     *      name 必须为  AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME
     *
     * @return
     */
//    @Bean(name = "AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME")
//    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
//        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
//        // 替换原来的注解处理，使用我们自定义的注解
//        autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
//
//        return autowiredAnnotationBeanPostProcessor;
//    }

    /**
     *  方式二:
     *          将 三种方式全部加入到 里面去
     * @return
     */
//    @Bean(name = "AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME")
//    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
//        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
//        // 替换原来的注解处理，使用我们自定义的注解
//        Set<Class<? extends Annotation>> set = new  LinkedHashSet<>(Arrays.asList(Autowired.class,InjectedUser.class, Inject.class));
//        autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationTypes(set);
//
//        return autowiredAnnotationBeanPostProcessor;
//    }

    /**
     * 方式三 ：
     *      利用顺序的方式来处理
     *      这种情况下 ，我们就会存在两个BeanProcessor 来同时处理
     * @return
     */
    @Bean(name = "AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME")
    @Order(Ordered.LOWEST_PRECEDENCE - 3)
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor(){
        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        // 替换原来的注解处理，使用我们自定义的注解
        autowiredAnnotationBeanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);

        return autowiredAnnotationBeanPostProcessor;
    }



    public static void main(String[] args) {
        // 创建 BeanFactory
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // xml Bean定义信息 Reader
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
        // 加载配置信息  ，解析 装载 配置文件
        xmlBeanDefinitionReader.loadBeanDefinitions("classpath:/META-INF/dependency-lookup-context.xml");

        // 注册 configuration Class (配置类)
        applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);

        // 启动Spring 应用上下文
        applicationContext.refresh();

        AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);


       // System.out.println("user : " +  demo.user);
       // System.out.println("users :" + demo.userMap);
        System.out.println(demo.optionalUser);

        System.out.println(demo.injectUser);

        System.out.println(demo.injectedUser);

        // 关闭应用上下文
        applicationContext.close();


    }


}
